/*******************************************************************************
 * Copyright (c) 2001, 2002 Boris Pruessmann and others. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Common Public License v0.5 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors: Boris Pruessmann - Initial implementation.
 ******************************************************************************/
package net.sourceforge.perforce.ui.dialogs;

import net.sourceforge.perforce.core.resources.LocalResource;
import net.sourceforge.perforce.core.syncinfo.ResourceSyncInfo;

import org.eclipse.core.resources.IFile;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;

/**
 * @version $Revision: 488 $
 * @author <a href="mailto:bpruessmann@users.sourceforge.net">Boris
 *         Pruessmann</a>
 */
public class ConfirmationDialog extends Dialog {

  /** Initial count of items to display in list. */
  private static final int LIST_ITEM_COUNT = 5;

  /** Array of button labels. */
  private static final String[] BUTTON_LABELS =
      {IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL};

  /** Index of default button. */
  private static final int DEFAULT_BUTTON_INDEX = 0;

  /** Stores the title of the dialog. */
  private String title;

  /** Stores the message of the dialog. */
  private String message;

  /** Stores the files that appear in the details area. */
  private IFile[] files;

  /** Stores the strings that appear in the details area. */
  private String[] strings;

  /** Holds the dialog's buttons */
  private Button[] buttons;

  /** Holds the button to toggle the detail area. */
  private Button detailsButton;

  /** List representing the details. */
  private List list;

  /** Indicates whether the list has been populated or not. */
  private boolean listCreated = false;

  /**
   * Creates a new Confirmation dialog and opens it.
   * 
   * @param parentShell the parent shell.
   * @param title the dialog title.
   * @param message the dialog message.
   * @param files the files.
   * @return true if the user confirmed the operation.
   */
  public static boolean openConfirmation(Shell parentShell, String title, String message,
      IFile[] files) {
    ConfirmationDialog dialog = new ConfirmationDialog(parentShell, title, message, files);

    return dialog.open() == 0;
  }

  /**
   * Creates a new Confirmation dialog and opens it.
   * 
   * @param parentShell the parent shell.
   * @param title the dialog title.
   * @param message the dialog message.
   * @param files the files.
   * @return true if the user confirmed the operation.
   */
  public static boolean openConfirmation(Shell parentShell, String title, String message,
      String[] files) {
    ConfirmationDialog dialog = new ConfirmationDialog(parentShell, title, message, files);

    return dialog.open() == 0;
  }


  /**
   * Constructor for ConfirmationDialog.
   * 
   * @param parentShell the parent shell.
   * @param dialogTitle the dialog title.
   * @param message the dialog message.
   * @param files the files.
   */
  private ConfirmationDialog(Shell parentShell, String dialogTitle, String message, IFile[] files) {
    super(parentShell);

    this.title = dialogTitle;
    this.message = message;
    this.files = files;
    setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE | SWT.APPLICATION_MODAL);
  }

  /**
   * Constructor for ConfirmationDialog.
   * 
   * @param parentShell the parent shell.
   * @param dialogTitle the dialog title.
   * @param message the dialog message.
   * @param strings the files (as string).
   */
  private ConfirmationDialog(Shell parentShell, String dialogTitle, String message, String[] strings) {
    super(parentShell);

    this.title = dialogTitle;
    this.message = message;
    this.strings = strings;
    setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE | SWT.APPLICATION_MODAL);
  }


  @Override
  protected void buttonPressed(int id) {
    if (id == IDialogConstants.DETAILS_ID) {
      toggleDetailsArea();
    } else {
      super.buttonPressed(id);
    }
  }

  @Override
  protected void configureShell(Shell shell) {
    super.configureShell(shell);
    shell.setText(title);
  }

  @Override
  protected void createButtonsForButtonBar(Composite parent) {
    buttons = new Button[BUTTON_LABELS.length];
    for (int i = 0; i < BUTTON_LABELS.length; i++) {
      String label = BUTTON_LABELS[i];
      buttons[i] = createButton(parent, i, label, DEFAULT_BUTTON_INDEX == i);
    }

    detailsButton =
        createButton(parent, IDialogConstants.DETAILS_ID, IDialogConstants.SHOW_DETAILS_LABEL,
            false);
  }

  @Override
  protected Control createDialogArea(Composite parent) {
    Composite composite = (Composite) super.createDialogArea(parent);
    ((GridLayout) composite.getLayout()).numColumns = 2;

    Image image = getImage();
    if (image != null) {
      Label label = new Label(composite, 0);
      image.setBackground(label.getBackground());
      label.setImage(image);
      label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_CENTER
          | GridData.VERTICAL_ALIGN_BEGINNING));
    }

    // create message
    if (message != null) {
      Label label = new Label(composite, SWT.WRAP);
      label.setText(message);

      GridData data =
          new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL
              | GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_CENTER);

      data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH);

      label.setLayoutData(data);
      label.setFont(parent.getFont());
    }

    return composite;
  }

  /**
   * Called to retrieve the dialog's image.
   * 
   * @return the image.
   */
  protected Image getImage() {
    return JFaceResources.getImageRegistry().get(DLG_IMG_QUESTION);
  }

  /**
   * Called to create the detail area.
   * 
   * @param parent the parent composite.
   * @return the detail area.
   */
  protected List createDropDownList(Composite parent) {
    // create the list
    list = new List(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);

    // fill the list
    populateList(list);

    GridData data =
        new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL
            | GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL);

    data.heightHint = list.getItemHeight() * LIST_ITEM_COUNT;
    list.setLayoutData(data);
    listCreated = true;
    return list;
  }


  /**
   * Called to populate the given list.
   * 
   * @param list the list.
   */
  private void populateList(List list) {
    if (files != null) {
      for (int i = 0, length = files.length; i < length; i++) {
        IFile file = files[i];

        ResourceSyncInfo resourceSyncInfo = LocalResource.createFromResource(file).getSyncInfo();
        list.add(resourceSyncInfo.getDepotFileName());
      }
    } else {
      for (int i = 0, length = strings.length; i < length; i++) {
        list.add(strings[i]);
      }
    }
  }

  /** Called to toggle visibility of the detail area. */
  private void toggleDetailsArea() {
    Point windowSize = getShell().getSize();
    Point oldSize = getContents().computeSize(SWT.DEFAULT, SWT.DEFAULT);

    if (listCreated) {
      list.dispose();
      listCreated = false;
      detailsButton.setText(IDialogConstants.SHOW_DETAILS_LABEL);
    } else {
      list = createDropDownList((Composite) getContents());
      detailsButton.setText(IDialogConstants.HIDE_DETAILS_LABEL);
    }

    Point newSize = getContents().computeSize(SWT.DEFAULT, SWT.DEFAULT);

    getShell().setSize(new Point(windowSize.x, windowSize.y + (newSize.y - oldSize.y)));
  }
}
